package service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/vueadmin/app/admin/internal/dto"
	"github.com/vueadmin/app/admin/internal/model"
	"github.com/vueadmin/app/admin/internal/svc"
	"github.com/vueadmin/app/admin/internal/vo"
	"github.com/vueadmin/pkg/cache"
	"github.com/vueadmin/utils/conv"
	"time"
)

type logService struct {
	svcCtx *svc.ServiceContext
}

func NewLogService(svcCtx *svc.ServiceContext) *logService {
	return &logService{
		svcCtx: svcCtx,
	}
}

/**
 * @description(数据列表)
 * @buildcode(true)
*/
func (p logService) GetPageList(req *dto.LogPageReq) ([]*vo.LogList, int64, error) {
	var (
		entity model.Log
		list  []*vo.LogList
		count int64
	)
	query := p.svcCtx.Db.Model(&entity)
	if !conv.IsEmpty(req.Id) {
		query = query.Where("id = ?", req.Id)
	}
	if !conv.IsEmpty(req.ApplicationName) {
		query = query.Where("application_name = ?", req.ApplicationName)
	}
	if !conv.IsEmpty(req.Type) {
		query = query.Where("type = ?", req.Type)
	}
	if !conv.IsEmpty(req.Username) {
		query = query.Where("username = ?", req.Username)
	}
	if !conv.IsEmpty(req.CreateTime){
		query = query.Where("create_time BETWEEN ? AND ?", conv.UnixTime(req.CreateTime[0]), conv.UnixTime(req.CreateTime[1]))
	}
	orderBy := "id desc"
	if !conv.IsEmpty(req.Sort) && !conv.IsEmpty(req.Order) {
		orderBy = fmt.Sprintf("%s %s", req.Sort, req.Order)
	}
	query.Count(&count)
	if err := query.Limit(req.Limit).Offset((req.Page - 1) * req.Limit).Order(orderBy).Find(&list).Error; err != nil {
		return nil, 0, err
	}
	return list, count, nil
}

/**
 * @description(删除)
 * @buildcode(true)
*/
func (p logService) Delete(req *dto.LogDeleteReq) error {
	query := p.svcCtx.Db
	query = query.Where("id IN ?", req.Id)
	if err := query.Delete(&model.Log{}).Error; err != nil {
		return err
	}
	return nil
}

/**
 * @description(查看详情)
 * @buildcode(true)
*/
func (p logService) Detail(req *dto.LogDetailReq) (*vo.LogDetail, error) {
	var info vo.LogDetail
	query := p.svcCtx.Db.Model(&model.Log{})
	if err := query.Where("id = ?",req.Id).Limit(1).First(&info).Error; err != nil {
		return nil, err
	}
	return &info, nil
}

/**
 * @description(导出)
 * @buildcode(true)
*/
func (p logService) Export(req *dto.LogPageReq) ([]*vo.LogExport,int64, error) {
	var (
		entity model.Log
		list []*vo.LogExport
		count int64
	)
	query := p.svcCtx.Db
	if !conv.IsEmpty(req.Id) {
		query = query.Where("id = ?", req.Id)
	}
	if !conv.IsEmpty(req.ApplicationName) {
		query = query.Where("application_name = ?", req.ApplicationName)
	}
	if !conv.IsEmpty(req.Type) {
		query = query.Where("type = ?", req.Type)
	}
	if !conv.IsEmpty(req.Username) {
		query = query.Where("username = ?", req.Username)
	}
	if !conv.IsEmpty(req.CreateTime){
		query = query.Where("create_time BETWEEN ? AND ?", conv.UnixTime(req.CreateTime[0]), conv.UnixTime(req.CreateTime[1]))
	}
	order := "id desc"
	if !conv.IsEmpty(req.Sort) && !conv.IsEmpty(req.Order) {
		order = fmt.Sprintf("%s %s", req.Sort, req.Order)
	}
	if err := query.Model(&entity).Order(order).Limit(req.Limit).Offset((req.Page - 1) * req.Limit).Find(&list).Error; err != nil {
		return nil,0, err
	}
	for k,v := range list{
		list[k].Type = conv.GetItemVal(v.Type,`[{"key":"登录日志","label_color":"info","val":"1"},{"key":"操作日志","label_color":"warning","val":"2"},{"key":"异常日志","label_color":"danger","val":"3"}]`)
		list[k].CreateTime = conv.DateTime(conv.Int64(v.CreateTime))
	}
	if req.Page == 1{
		cache.New(p.svcCtx.Redis).Delete("log_count")
	}
	cache_count := cache.New(p.svcCtx.Redis).Get("log_count")
	if cache_count == "" {
		query.Model(&entity).Count(&count)
		cache.New(p.svcCtx.Redis).Set("log_count", conv.String(count), 300*time.Second)
	} else {
		count = conv.Int64(cache_count)
	}
	return list,count, nil
}

/**
 * @description(查询sql下拉字段列表)
 * @buildcode(true)
*/
func (p logService) GetFieldList(c *gin.Context) (map[string]interface{}, error) {
	var (
		ApplicationName []*vo.LogApplicationName
	)
	if err := p.svcCtx.Db.Raw(`select app_dir,application_name from cd_application`).Scan(&ApplicationName).Error; err != nil {
		return nil, err
	}
	data := make(map[string]interface{})
	data["application_names"] = ApplicationName
	return data, nil
}

